/*
 * client_server_thread.cpp
 *
 *  Created on: 2009-12-21
 *      Author: karooolek
 */

#include "server_thread.h"
#include "server.h"

ServerThread::ServerThread() :
	_server(NULL), _conn(NULL), _name()
{
}

ServerThread::ServerThread(Server* server, Connection *conn) :
	_server(server), _conn(conn), _name()
{
}

ServerThread::~ServerThread()
{
	if(_conn)
	{
		_conn->close();
	}
}

void ServerThread::_run()
{
	if(!_server || !_conn)
	{
		Log::instance()->error("Server thread is uninitialized. Must stop.");
		return;
	}

	AnyMessage msg;
	InfoMessage greetMsg;
	greetMsg.type = MSG_GREETING;
	InfoMessage successMsg;
	successMsg.type = MSG_SUCCESS;
	InfoMessage failMsg;
	failMsg.type = MSG_FAILURE;
	InfoMessage pingMsg;
	pingMsg.type = MSG_PING;
	InfoMessage exitMsg;
	exitMsg.type = MSG_EXIT;

	// obsluguj wiadomosci od polaczenia
	while(!_stop)
	{
		// odbierz wiadomosc
		memset(&msg, 0, sizeof(msg));
		if(!_conn->receive((uint8 *) &msg, sizeof(msg)))
		{
			// troche za dlugo czekamy...
			Log::instance()->warn("Connection with " + _name + " lost");
			stop();
			break;
		}

		// rozpoznaj typ
		switch(msg.client.type)
		{
		case MSG_GREETING:
			if(_name != "") _server->deleteClient(_name);
			_server->newClient(_name = String(msg.client.clientName));
			_conn->send((uint8 *)&successMsg, sizeof(successMsg));
			break;

		case MSG_CREATE_SEM:
			if(_name == "" || !_server->createSem(String(msg.sem.semName), _name))
			{
				_conn->send((uint8 *)&failMsg, sizeof(failMsg));
			}
			_conn->send((uint8 *)&successMsg, sizeof(successMsg));
			break;

		case MSG_DELETE_SEM:
			if(_name == "" || !_server->deleteSem(String(msg.sem.semName), _name))
			{
				_conn->send((uint8 *)&failMsg, sizeof(failMsg));
			}
			_conn->send((uint8 *)&successMsg, sizeof(successMsg));
			break;

		case MSG_P_SEM:
			if(_name == "" || !_server->pSem(String(msg.sem.semName), _name))
			{
				_conn->send((uint8 *)&failMsg, sizeof(failMsg));
			}
			_conn->send((uint8 *)&successMsg, sizeof(successMsg));
			break;

		case MSG_V_SEM:
			if(_name == "" || !_server->vSem(String(msg.sem.semName), _name))
			{
				_conn->send((uint8 *)&failMsg, sizeof(failMsg));
			}
			_conn->send((uint8 *)&successMsg, sizeof(successMsg));
			break;

		case MSG_DEADLOCK:
//			std::cout << "Got deadlock suspition..." << std::endl;
			_server->checkDeadlock(String(msg.deadlock.clientName),
									String(msg.deadlock.suspectName));
			break;

		case MSG_PING:
//			std::cout << "Got ping from " << _name << std::endl;
			break;

		case MSG_EXIT:
			stop();
			break;

		default:
			// other messages are doing it wrong
			_conn->send((uint8 *)&failMsg, sizeof(failMsg));
			break;
		}

	}

	// pozegnaj klienta
	_conn->send((uint8 *)&exitMsg, sizeof(exitMsg));

	// zamknij polaczenie
	_conn->close();

	// usun klienta z serwera
	_server->deleteClient(_name);
}

